package com.douqu.game.core.entity.battle;

import com.douqu.game.core.e.E_BattleAObjectStatus;
import com.douqu.game.core.entity.Attribute;
import com.douqu.game.core.entity.GameObject;
import com.douqu.game.core.entity.Skill;
import com.douqu.game.core.entity.common.TwoTuple;
import com.douqu.game.core.controller.BattleParentController;
import com.douqu.game.core.controller.SpriteController;
import com.douqu.game.core.entity.ext.ExtInfo;
import com.douqu.game.core.factory.ConstantFactory;
import com.douqu.game.core.factory.DataFactory;
import com.douqu.game.core.protobuf.SGCommonProto;

import java.util.List;

/**
 * 战斗中的对象
 * Created by bean on 2017/7/27.
 */
public class BattleAObject extends GameObject{

    /**
     * 所属主人
     */
    protected SpriteController spriteController;

    protected BattleParentController battleParentController;
//
//    /**
//     * 战斗单位
//     */
//    protected Sprite battleSprite;

    protected E_BattleAObjectStatus status;

    /**
     * 对象ID,对应配置文件里的ID
     */
    protected int objectId;

    protected int hp;

    protected int maxHp;

    protected int physicsAtk;

    protected int punctureAtk;

    protected int magicAtk;

    protected int defType;

    protected int physicsDef;

    protected int punctureDef;

    protected int magicDef;

    /** 力量 */
    protected int power;
    /** 敏捷 */
    protected int agility;
    /** 智力 */
    protected int wisdom;

    protected int fc;

    protected BattleSkill[] cdSkills;

    protected BattleSkill defaultSkill;



    /**
     * 单位类型
     * 1.地面
     * 2.飞行
     */
    public int unitType;

    protected int teamNo;

    /**
     * 位置
     */
    public Position position;

//    /**
//     * 攻击目标
//     */
//    protected BattleAObject atkTarget;

    /**
     * 前进的目标
     */
    protected BattleAObject goTarget;

    /**
     * 是否可穿越
     */
    protected boolean isFree = false;

    public BattleAObject(SpriteController spriteController, int uniqueId)
    {
        this.id = uniqueId;
        this.spriteController = spriteController;
        if(spriteController.getParent() instanceof BattleParentController)
        {
            this.battleParentController = (BattleParentController) spriteController.getParent();
        }
        else
        {
            System.out.println("BattleAObject Init Error: parent is not BattleController!" + spriteController.getParent());
        }
    }


    public void update(int updateTime)
    {
        defaultSkill.update(updateTime);

        if(defaultSkill.checkTimeEffectStart())
        {
            defaultSkill.timeEffectStart(battleParentController);
        }

        for(BattleSkill skill : cdSkills)
        {
            skill.update(updateTime);

            if(skill.checkTimeEffectStart())
            {
                skill.timeEffectStart(battleParentController);
            }
        }
    }

    /**
     * 是否是同一个目标对象
     * @param target
     * @return
     */
    public boolean isSameGoTarget(BattleAObject target)
    {
        if(goTarget == null || target == null)
            return false;

        return goTarget.getId() == target.getId() && goTarget.getPosition().isSame(target.getPosition());
    }



    /**
     * 检测攻击范围内有没有敌人
     */
    protected int getAtkRange()
    {
        return -1;
    }

//    public void addAtkTarget(BattleAObject target)
//    {
//        this.status = E_BattleAObjectStatus.BATTLING;
//        this.goTarget = null;
//    }

//    public void removeAtkTarget()
//    {
//        defaultSkill.releaseTime = 0;
//        defaultSkill.releaseCount = 0;
//    }

//    public void clearAtkTarget()
//    {
//        goTarget = null;
//        defaultSkill.setReleaseInfo(0);
//        status = E_BattleAObjectStatus.FREE;
//    }

    protected void addDefaultAtk(List<BattleAObject> targets)
    {
        this.status = E_BattleAObjectStatus.BATTLING;
        this.goTarget = null;
        defaultSkill.addAtkTarget(targets);
    }

    protected void addDefaultAtk(BattleAObject target)
    {
        this.status = E_BattleAObjectStatus.BATTLING;
        this.goTarget = null;
        defaultSkill.addAtkTarget(target);
    }


    protected void checkDefaultAtk()
    {
        if(!defaultSkill.isHaveTarget())
            return;

        defaultSkill.checkTargetDie();

        if(!defaultSkill.isHaveTarget())
            this.status = E_BattleAObjectStatus.FREE;
    }

    public void addHP(int value)
    {
        hp += value;
        hp = hp < 0 ? 0 : hp;
    }

    public int getAtk(Skill skill)
    {
        if(skill.effectType == ConstantFactory.EFFECT_TYPE_HP_SUB_PHY_ATK)
            return physicsAtk;

        if(skill.effectType == ConstantFactory.EFFECT_TYPE_HP_SUB_PUN_ATK)
            return punctureAtk;

        if(skill.effectType == ConstantFactory.EFFECT_TYPE_HP_SUB_MAG_ATK)
            return magicAtk;

        return 0;
    }

    /**
     * 获取复合属性
     * @return
     */
    public int getExtAttr(Skill skill)
    {
        SpriteBattleTmp spriteBattleTmp = spriteController.getAttachment();
        if(skill.effectType == ConstantFactory.EFFECT_TYPE_HP_SUB_PHY_ATK)
            return spriteBattleTmp.masterSoldier.power;

        if(skill.effectType == ConstantFactory.EFFECT_TYPE_HP_SUB_PUN_ATK)
            return spriteBattleTmp.masterSoldier.agility;

        if(skill.effectType == ConstantFactory.EFFECT_TYPE_HP_SUB_MAG_ATK)
            return spriteBattleTmp.masterSoldier.wisdom;

        return 0;
    }

//    /**
//     * 获取复合属性
//     * @return
//     */
//    public int getExtAttr(int type)
//    {
//        SpriteBattleTmp spriteBattleTmp = spriteController.getAttachment();
//        if(type == ConstantFactory.AD_TYPE_PHYSICS)
//            return spriteBattleTmp.masterSoldier.power;
//
//        if(type == ConstantFactory.AD_TYPE_PUNCTURE)
//            return spriteBattleTmp.masterSoldier.agility;
//
//        if(type == ConstantFactory.AD_TYPE_MAGIC)
//            return spriteBattleTmp.masterSoldier.wisdom;
//
//        return 0;
//    }


//    public int getDef()
//    {
//        if(defType == ConstantFactory.AD_TYPE_PHYSICS)
//            return physicsDef;
//
//        if(defType == ConstantFactory.AD_TYPE_PUNCTURE)
//            return punctureDef;
//
//        if(defType == ConstantFactory.AD_TYPE_MAGIC)
//            return magicDef;
//
//        return 0;
//    }

    public int getDef(Skill skill)
    {
        if(skill.effectType == ConstantFactory.EFFECT_TYPE_HP_SUB_PHY_ATK)
            return physicsDef;

        if(skill.effectType == ConstantFactory.EFFECT_TYPE_HP_SUB_PUN_ATK)
            return punctureDef;

        if(skill.effectType == ConstantFactory.EFFECT_TYPE_HP_SUB_MAG_ATK)
            return magicDef;

        return 0;
    }

//    public int addAttribute(int id, int value)
//    {
//        Attribute attribute = DataFactory.getInstance().getGameObject(DataFactory.ATTRIBUTE_KEY, id);
//        if(attribute != null)
//        {
//            String v = getVariable(attribute.name);
//            int newValue = Integer.parseInt(v) + value;
//            newValue = newValue < 0 ? 0 : newValue;
//            setVariable(attribute.name, newValue+"");
//
//            return newValue;
//        }
//
//        return 0;
//    }

    /**
     * 前进
     */
    public void go()
    {
           //在子类实现
    }

    public boolean checkCanAtk(BattleAObject target)
    {
        return false;
    }


    /**
     * 检测攻击目标
     * @param targetList
     * @return
     */
    public TwoTuple<List<BattleAObject>, BattleAObject> checkAtkTarget(List<BattleAObject> targetList)
    {
        //在子类实现
        return null;
    }


//    /**
//     * 检查当前的攻击目标
//     * @return true表示正和攻击目标打的如火如荼 false表示要重新找攻击目标了
//     */
//    public boolean checkDefaultSkillCurAtkTargetOK(long currentTime)
//    {
//        return false;
//    }

    public void checkDefaultSkillTarget(long currentTime)
    {

    }


    /**
     * 获取到目标的路线
     * @param target
     */
    public void checkRoute(BattleAObject target)
    {

    }


    /**
     * 是否能克制对方
     * @param target
     * @return
     */
    public boolean isRestrict(BattleAObject target)
    {
        return false;
    }


    /**
     * 是否在播放效果动作中
     * @return
     */
    public boolean isEffectActioning()
    {
        if(defaultSkill.isTimeActioning())
            return true;

        for(BattleSkill skill : cdSkills)
        {
            if(skill.isTimeActioning())
                return true;
        }

        return false;
    }


    /**
     * 获取伤害值
     * @param target
     * @return
     */
    public int getDamage(BattleAObject target, Skill skill)
    {
        //伤害值 =[（攻击方最终攻击力-防御方最终防御力*技能系数+(技能等级+X)*技能基础伤害] * [1 + (攻击方复合属性-防御方复合属性)*0.005]
        //攻击方最终攻击力根据技能的效果类型来定
        //防御方最终防御力根据技能的效果类型来定
        //攻击方复合属性：物理攻击->力量，穿刺攻击->敏捷，魔法攻击->智力
        //防御方复合属性：根据攻击方的攻击类型业取值，取值方式同上
        //技能系数：技能里的ratio值
        //技能等级：技能是有成长体系的，会升级
        //X：初始化配置里的skillPlusX

        //攻击方最终攻击力
        int atk = getAtk(skill);
        //（攻击方最终攻击力-防御方最终防御力）* 技能系数
        double temp1 = (atk - target.getDef(skill)) * skill.ratio;
        //(技能等级+X)*技能基础伤害
        double temp2 = (skill.lv + DataFactory.getInstance().getInitData().skillPlusX) * skill.effectValue;
        //(攻击方复合属性-防御方复合属性)，若< -100 则= -100
        int extAtt = getExtAttr(skill) - target.getExtAttr(skill);
        extAtt = extAtt < -100 ? -100 : extAtt;
        double xishu = 1 + extAtt * 0.005;
        double temp = (temp1 + temp2) * xishu;
        int result = (int) Math.ceil(temp);
        result = result <= 0 ? 1 : result;
        return result;
    }



    /**
     * 获取加血的值
     * @param skill
     * @return
     */
    public int getAddHP(Skill skill)
    {
        //加血值=目标智力值*技能系数+（技能等级+X）*技能基础值
        double temp = wisdom * skill.ratio + (skill.lv + DataFactory.getInstance().getInitData().skillPlusX) + skill.effectValue;
        return (int) temp;
    }


    public BattleSkill getCDSkill(int skillId)
    {
        for(BattleSkill skill : cdSkills)
        {
            if(skill.getId() == skillId)
                return skill;
        }
        return null;
    }


    /**
     * 检测出场技能
     */
    public void checkBornSkill()
    {
        System.out.println("BattleAObject checkBornSkill+++++++++++++++++++");
        if(cdSkills == null)
            return;

        for(BattleSkill skill : cdSkills)
        {
            if(skill.getSkill().type == ConstantFactory.SKILL_TYPE_BORN)
            {
//                if(spriteController.getAttachment().getCurCrystal() < skill.getSkill().crystal)
//                    continue;
                System.out.println("检测出生技能............");
                skill.release(battleParentController.getSkillTargets(skill), position, 0);
            }
        }
    }

    /**
     * 检测死亡技能
     */
    public void checkDieSkill()
    {
        if(cdSkills == null)
            return;

        for(BattleSkill skill : cdSkills)
        {
            if(skill.getSkill().type == ConstantFactory.SKILL_TYPE_DIE)
            {
//                if(spriteController.getAttachment().getCurCrystal() < skill.getSkill().crystal)
//                    continue;

                skill.release(battleParentController.getSkillTargets(skill), position, 0);
            }
        }
    }

    /**
     * 检测CD技能
     */
    public boolean checkCDSkill(long currentTime)
    {
        if(cdSkills == null)
            return false;

        boolean result = false;

        for(BattleSkill skill : cdSkills)
        {
            if(skill.getSkill().type == ConstantFactory.SKILL_TYPE_CD)
            {
                if(skill.cdTime > 0)
                    continue;

//                if(spriteController.getAttachment().getCurCrystal() < skill.getSkill().crystal)
//                    continue;

                skill.release(battleParentController.getSkillTargets(skill), position, currentTime);

                result = true;
            }
        }

        return result;
    }


    /**
     * 获取损失的HP
     * @return
     */
    public int getLossHp()
    {
        return maxHp - hp;
    }


    public SGCommonProto.BattleSoldier.Builder parseBattleSoldier()
    {
        SGCommonProto.BattleSoldier.Builder data = SGCommonProto.BattleSoldier.newBuilder();
        data.setUniqueId(id);
        data.setSoldierId(objectId);
        data.setPos(position.parsePos());
        data.setTeamNo(teamNo);
        data.setMaxHP(maxHp);
        data.setHp(hp);
        return data;
    }

    public void setStatus(E_BattleAObjectStatus status) {
        this.status = status;
    }

    public E_BattleAObjectStatus getStatus() {
        return status;
    }

    public boolean isDie()
    {
        return hp <= 0;
    }

    public boolean isFree() {
        return isFree;
    }

    public void setFree(boolean isFree) {
        this.isFree = isFree;
    }


    public int getHp() {
        return hp;
    }

    public void setHp(int hp) {
        this.hp = hp;
    }

    public int getTeamNo() {
        return teamNo;
    }

    public void setTeamNo(int teamNo) {
        this.teamNo = teamNo;
    }

    public Position getPosition() {
        return position;
    }

    public void setPosition(Position position) {
        this.position = position;
    }

    public SpriteController getSpriteController() {
        return spriteController;
    }

    public void setSpriteController(SpriteController spriteController) {
        this.spriteController = spriteController;
    }


    public int getMaxHp() {
        return maxHp;
    }

    public BattleAObject getGoTarget() {
        return goTarget;
    }

    public void setGoTarget(BattleAObject goTarget) {
        this.goTarget = goTarget;
    }

    public int getObjectId()
    {
        return objectId;
    }




    @Override
    public String toString() {
        return "BattleAObject{" +
                "teamNo=" + teamNo +
                ", position=" + position +
                "} " + super.toString();
    }
}
